package org.example.downloadtest.ctl;

import org.apache.coyote.Constants;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@RestController
@RequestMapping("/down")
public class DownCtl {
    @GetMapping
    public void down(HttpServletRequest request, HttpServletResponse response, @RequestParam("filename")String filename) throws IOException {
        if (!Boolean.parseBoolean(request.getAttribute(Constants.SENDFILE_SUPPORTED_ATTR).toString())) {
            response.getWriter().write("unsupported");
            return;
        }
        response.setHeader(HttpHeaders.ACCEPT_RANGES,"bytes");
        String rangeHeader=request.getHeader(HttpHeaders.RANGE);
        String basePath="C:/Users/zhjun/Downloads";
        Path file = Paths.get(basePath,filename);
        String contentType = Files.probeContentType(file);
        if (contentType == null) {
            contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        }
        response.setContentType(contentType);
        response.setHeader(HttpHeaders.ETAG,"this is etag");
        response.setHeader(HttpHeaders.LAST_MODIFIED,String.valueOf(file.toFile().lastModified()));
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(filename, StandardCharsets.UTF_8).build().toString());
        request.setAttribute(Constants.SENDFILE_FILENAME_ATTR, Paths.get(basePath,filename).toFile().getPath());
//        System.out.println(rangeHeader);
        if (rangeHeader==null||rangeHeader.equals("")){
            response.setContentLengthLong(file.toFile().length());
            request.setAttribute(Constants.SENDFILE_FILE_START_ATTR, 0L);
            request.setAttribute(Constants.SENDFILE_FILE_END_ATTR, file.toFile().length());
        }else{
            response.setStatus(206);
            System.out.println(rangeHeader);
            //range请求头告诉我们从这个字节开始传输，而不是已经拥有了这么多长度的数据
            long start = Long.valueOf(rangeHeader.replace("bytes=", "").replace("-", ""));
            //在这里，一个header类似于bytes 10-20/21，也就是说结尾必须比真正长度小1
            //也就是说，bytes开头的10代表从下标10开始直到下标20，也就是最后一个元素，而 真正的长度则是21
            response.setHeader(HttpHeaders.CONTENT_RANGE,"bytes "+start+"-"+(file.toFile().length()-1)+"/"+file.toFile().length());
            //而content-length必须是真正需要传输的长度，即存在数据块0，1，2，3，4，5，如果range要求从1开始，那么长度是6-1=5
            response.setContentLengthLong(file.toFile().length()-start);
            request.setAttribute(Constants.SENDFILE_FILE_START_ATTR, start);
            request.setAttribute(Constants.SENDFILE_FILE_END_ATTR, file.toFile().length());
        }

    }
}
